#include <SDL/SDL_timer.h>

#include "Renderer.h"

class Renderer_Cleaner {
public:
    ~Renderer_Cleaner() {
        Renderer::destroy();
    }
} renderer_cleaner_instaninstce;

Renderer* Renderer::instance = NULL;

Renderer::Renderer() : layer_list(*(Layer_List::get_instance())),
        viewport(*(Viewport::get_instance())) {
    last_update_time = 0;
    update_interval = 1000/viewport.refresh_rate;
    if (Debug::test(DEBUG_CREATE_DELETE)) {
        cout << "Renderer Created" << endl;
    }

}

Renderer* Renderer::get_instance() {
    if(!instance) {
        instance = new Renderer();
    }
    return instance;
}

void Renderer::destroy() {
    if( !instance ) {
        return;
    }
    delete(instance);
    instance = NULL;
    if (Debug::test(DEBUG_CREATE_DELETE)) {
        cout << "Renderer Destroyed" << endl;
    }
}

void Renderer::execute() {
    render();
}

Renderer::~Renderer() { }

void Renderer::render() {
    Uint32 cur_time, time_diff;
    while (viewport.keep_looping) {
        if (Debug::test(DEBUG_THREAD)) {
            cout << "Render executed" << endl;
        }
        cout.flush();

        viewport_x = viewport.renderer_wx;
        viewport_y = viewport.renderer_wy;

        layer_list.lock();
        list<Layer *>::iterator begin, end = layer_list.getListIteratorEnd();

        for (begin = layer_list.getListIteratorBegin(); begin != end; begin++) {
            if ((*begin)->isVisible()) {
                (*begin)->start();
            }
            if (Debug::test(DEBUG_THREAD)) {
                cout << "started layer" << (*begin)->getLayerId() << endl;
            }
        }

        SDL_FillRect(viewport.get_surface(), NULL, viewport.colorkey);

        for (begin = layer_list.getListIteratorBegin(); begin != end; begin++) {
            if ((*begin)->isVisible()) {
                (*begin)->join();

                if (Debug::test(DEBUG_THREAD)) {
                    cout << "layer " << (*begin)->getLayerId() << "joined" << endl;
                }

                SDL_BlitSurface((*begin)->get_surface(), NULL,
                    viewport.get_surface(), NULL);
            }
        }
        cspointer.draw();
        layer_list.unlock();

        cur_time = SDL_GetTicks();
        time_diff = cur_time - last_update_time;

        if( time_diff < update_interval) {
            SDL_Delay(update_interval - time_diff);
            last_update_time = SDL_GetTicks();
        } else {
            last_update_time = cur_time;
        }
        viewport.update();
    }
    if (Debug::test(DEBUG_THREAD)) {
        cout << "renderer loop  BROKEN" << endl;
    }
}
